/* 
let obj = {
    x: 1,
    y: [10, 20]
};
let obj2 = obj;
let obj3 = {
    ...obj2
};
obj2.x = 100;
obj2.y[1] = 30;
obj3.x = 200;
obj3.y[2] = 40;
obj = obj3.y = {
    x: 0,
    y: [1, 2]
};
console.log(obj, obj2, obj3); 
*/

/* 
let x = 5;
const fn = function fn(x) {
    return function (y) {
        console.log(y + (++x));
    }
};
let f = fn(6);
f(7);
fn(8)(9);
f(10);
console.log(x);
*/

/* let a = 0,
    b = 0;
function A(a) {
    A = function (b) {
        alert(a + b++);
    };
    alert(a++);
}
A(1);
A(2); */


//=============================
/*
 结果分析：下面的代码执行，迭代五次，设置五个定时器（等待时间分别为1000ms~5000ms）；当定时器到时间后，依次执行对应的callback方法，输出的结果都是5！
 阐述原因：
   @1 循环是同步，定时器是异步，每一轮循环设置定时器后，无需等待定时器的监听执行，继续执行下一轮循环「也就是定时器到时间触发执行的时候，循环早已经结束了」
   @2 循环中使用 var 声明变量，不会产生块级私有上下文，i 都是全局的
     + 循环结束，全局的 i=5
     + 定时器触发执行，需要输出 i 的值，此时的i不是函数私有变量，会按照作用域链查找全局上下文中的i，也就是5
 */
/* for (var i = 0; i < 5; i++) {
    setTimeout(function () {
        console.log(i);
    }, (i + 1) * 1000);
} */

/*
 解决方案一：在每一轮循环的时候，手动创建一个“闭包”，让其内部有一个 i 的私有变量，分别存储当前循环的i的值；定时器触发执行的时候，用到的i，直接去我们创建的闭包中查找即可！！
 */
/* // 基于自执行函数执行，产生闭包
for (var i = 0; i < 5; i++) {
    (function (i) {
        setTimeout(() => {
            console.log(i);
        }, (i + 1) * 1000);
    })(i)
} 

// 基于let产生闭包
for (let i = 0; i < 5; i++) {
    setTimeout(() => {
        console.log(i);
    }, (i + 1) * 1000);
}  */


/*
 解决方案二：还可以利用定时器的第三个参数处理
   setTimeout([callback],[interval],params1,params2,...)
   第三个及以后参数，都是等待callback执行的时候，为其传递的实参值「底层原理还是闭包：每一次设置定时器，都会产生一个闭包，用来存储我们事先传递给定时器的实参值；当定时器触发执行的时候，再把闭包中存储的这些值，依次传递给callback函数」
 */
for (var i = 0; i < 5; i++) {
    setTimeout(
        (i) => {
            // i:私有变量，存储的值是之前设置定时器的时候，预先传递的值
            console.log(i);
        },
        (i + 1) * 1000,
        i
    );
}